package me.ahoukuse.clipboard;

import android.app.Service;
import android.content.ClipData;
import android.content.ClipDescription;
import android.content.ClipboardManager;
import android.content.Context;
import android.content.Intent;
import android.os.IBinder;
import android.util.Log;
import android.widget.Toast;
import androidx.annotation.Nullable;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.Serializable;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;


class AhoService implements Runnable {
    private int    port;
    private Context context;
    AhoService(int port,Context context){
        this.port = port;
        this.context = context;
    }

    @Override
    public void run() {
        byte[] op_code = new byte[1];
        byte[] length  = new byte[2];
        byte[] context;
        ServerSocket ss = null;
        try {
            ss = new ServerSocket(this.port);
        } catch (IOException e) {
            e.printStackTrace();
        }
        try {

            Log.d("INFO", "run: AhoServer running");
            while (true) {
                assert ss != null;
                Socket socket = ss.accept();
                InputStream is = socket.getInputStream();
                is.read(op_code,0,1);
                is.read(length,0,2);
                int size = (length[0] << 8) + length[1];
                context = new byte[size-3];
                is.read(context,0,size-3);
                String co = new String(context);
                ClipboardHelper.setClipboardText(this.context,co);
                Log.d("Receive", String.format("op_code %d length %d context",(int)op_code[0],size));
                is.close();

            }
        } catch (IOException e) {
            e.printStackTrace();

        } finally {
            try {
                ss.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

    }
}

class AhoPack implements Serializable {
    private              byte    op_code;
    private              int     size;
    private              byte[]  context;
    AhoPack(byte op_code,String context){
        this.op_code = op_code;
        this.context = context.getBytes();
        size = this.context.length;
    }

    void writeTo(OutputStream out) throws IOException {
        int length = size + 3;
        byte[] buffer = new byte[length];
        buffer[0] = op_code;
        buffer[2] = (byte) (length     & 0xff);
        buffer[1] = (byte) (length>>8  & 0xff);
        System.arraycopy(context,0,buffer,3,size);
        out.write(buffer);
    }

}

class SocketThread implements Runnable {

    private String IP;
    private int port;
    private String msg;

    SocketThread(String IP,int port,String msg){
        this.IP = IP;
        this.port = port;
        this.msg = msg;
    }

    @Override
    public void run() {
        try {
            Socket socket = new Socket(IP,port);
            OutputStream out = socket.getOutputStream();
            AhoPack ahoPack =  new AhoPack((byte)1,msg);
            ahoPack.writeTo(out);
            out.close();
            socket.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}



public class BackService extends Service {
    private String IP_Addr = null;
    private int    port    = 0;
    private ExecutorService executorService;
    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }

    @Override
    public void onCreate() {
        super.onCreate();
        executorService  = Executors.newCachedThreadPool();

    }

    private String getClipBoardText() {
        ClipboardManager manager = (ClipboardManager) getSystemService(CLIPBOARD_SERVICE);
        assert manager != null;
        ClipData data = manager.getPrimaryClip();
        if (data != null){
            if (data.getDescription().hasMimeType(ClipDescription.MIMETYPE_TEXT_PLAIN)){
                CharSequence charSequence = data.getItemAt(0).getText();
                return charSequence.toString();
            }
        }
        return null;
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        CharSequence chars = intent.getCharSequenceExtra(Intent.EXTRA_TEXT);
        CharSequence IP = intent.getCharSequenceExtra("IP");
        if (this.port == 0) {
            this.port = intent.getIntExtra("Port", 7778);
            executorService.execute(new AhoService(2333, this));
        }
        Log.d("Info", String.format("Binding on %d", port));
        if(chars != null && IP == null){
            executorService.execute(new SocketThread(IP_Addr,port,chars.toString()));
            Toast.makeText(this, "完成!", Toast.LENGTH_SHORT).show();
        } else if(chars == null && IP != null){
            IP_Addr = IP.toString();
        }
        return super.onStartCommand(intent, flags, startId);
    }
}
